# encoding: utf-8
#!/usr/local/bin/python2.7
'''
NervuresDesignTool -- Outil de conception/simulation de parapentes Nervures

    Gui Cloison
    -> construit gui Cloison

@author:     Michel Le Berre, Pierre Puiseux    
@copyright:  2013 Nervures. All rights reserved.    
@license:    LGPL
@contact:    be@nervures.com
@deffield    updated: 31 Jan 2013
'''
#import PySide as PyQt4
import sys
sys.path.append("../")
import numpy as np
import pickle, cPickle
from config import DATA_DIR
from PyQt4 import QtGui
from PyQt4 import QtCore
from PyQt4.uic import loadUiType
from utilitaires import Path
from PyQt4.QtGui import (QWidget,)
from PyQt4.QtCore import Qt
from PyQt4.Qt import SIGNAL, SLOT
from config import SOURCES_DIR
from utilitaires.utilitaires import trace, alert, p2t, p2s, whoami, baryCentre
#from model.cloison.cloison import Cloison

from graphics.graphicsprofil import EGraphicsProfilItem, EGraphicsGabaritItem
from graphics.node import Noeud#, PhantomNode
from graphics.scene import EGraphicsScene
from graphics.view import EGraphicsView
from graphics.preferences import PolygonPrefs#, Parametres
from lecteur import LecteurExameca
from graphics.preferences import ScenePrefs

################################################
################################################
################################################
################################################
if sys.platform == 'win32' :   
    uifile = "shapeeditor.ui"
elif sys.platform == 'darwin' : 
    uifile = "shapeeditor.ui"
else : 
    uifile = "shapeeditor.ui"
    
UiguiShapeClass, UiguiShapeClassType = loadUiType(Path(SOURCES_DIR,"graphics",uifile))
class GuiProfilEditor(UiguiShapeClassType,UiguiShapeClass):
    u'''
    
    '''
#     param = Parametres
    def __init__(self, parent=None):
        UiguiShapeClassType.__init__(self, parent=None)
        QWidget.__init__(self)
        self.setupUi(self)
        ''' Tracé profil '''
        self.wgraphicsview = EGraphicsView()
        self.gv = self.wgraphicsview
        self.scene = EGraphicsScene(self)
        self.wgraphicsview.setScene(self.scene)
        self.layout().addWidget(self.wgraphicsview,2,0,3,6)
        '''Actions supplémentaires'''
        self.createActions()
        ''' Connections '''
        self.createConnections()
        '''Menus et toolbar'''
        self.createMenus()
        self.createToolBar()
        self.listundo = []
        self.graphicsstate = gst = {'numerotation' : False, 'showpoints':False, 'showgrid':True}
        self.showGrid()
        self.createGraphicsForTest()
        self.updateUi()
        self.recadre()
    
    def updateUi(self):
        bigitems = self.selectedBigItems()
        types = [type(item) for item in bigitems]
        ya_un_profil =  EGraphicsProfilItem in types
        ya_un_gabarit = EGraphicsGabaritItem in types
        trace(self, types, ya_un_profil)
        
        for widget in (
                       self.sb_rotation, 
                       self.tb_raz, 
                       self.dsb_homx, 
                       self.dsb_homy, 
                       self.tb_symetrieH, 
                       self.tb_symetrieV, 
                       self.cb_showpoints, 
                       self.cb_numerotation,
#                        self.pb_presize,
                       self.tb_aligner
                       ) :
            widget.setEnabled(ya_un_profil or ya_un_gabarit)
        if len(bigitems) == 1 :
            self.setGraphicsState(bigitems[0].graphicsstate) 
        else :
            self.setGraphicsState(None)
        
#             widget.setEnabled(not selecteditems == [])
    def setGraphicsState(self, gst=None):
        if gst is None : #valeurs par defaut
            gst = self.graphicsstate
            
#         self.cb_showgrid.setChecked(self.graphicsstate['showgrid'])
        
        self.cb_showpoints.setChecked(gst['showpoints'])
        self.cb_numerotation.setChecked(gst['numerotation'])
        
    def showGrid(self):
        self.view.showGrid(self.cb_showgrid.isChecked())
        self.view.update()
        
    def showPoints(self, value=True):
        for item in self.selectedBigItems() :
            item.afficherPoints(value)
    
    def showNumbers(self, value=True):
        for item in self.selectedBigItems() :
            item.numeroter(value)
    
    def createGraphicsForTest(self):
#         gparent = QtGui.QGraphicsRectItem(0,0,2,1)
#         self.scene.addItem(gparent)
#         self.scene.gparent = gparent
        filename =  Path(DATA_DIR,'Gabarits_txt','96777178-JB2ML-detail-H.txt')
        f = LecteurExameca(filename)
        points =  f.lire()
        gabarit = EGraphicsGabaritItem(points=points, editor=self)
        gabarit.afficherPoints(False)
        self.scene.gparent = gabarit
#         profil.setFlag(QtGui.QGraphicsItem.ItemIsMovable, False)
        self.scene.addItem(gabarit)
        filename =  Path(DATA_DIR,'Gabarits_txt','96777178-JB2ML-detail-F.txt')
        f = LecteurExameca(filename)
        points =  f.lire()
        gabarit = EGraphicsGabaritItem(points=points, editor=self)
        gabarit.afficherPoints(False)
        self.scene.gparent = gabarit
#         profil.setFlag(QtGui.QGraphicsItem.ItemIsMovable, False)
        self.scene.addItem(gabarit)
    
    def createActions(self):
        u'''
        Les actions sont créées dans designer.
        Elles sont transmises à la scène (dans scene.createActions())
        '''
        self.actionsinserer = [                       
#                                self.actionInsererEllipse, 
                               self.actionInsererPolyline,
                               self.actionInsererPolygone, 
                               self.actionInsererPoint,
                               ]
        self.actionsfichier = [
                            self.actionOuvrir, 
                            self.actionEnregistrerSous, 
                            self.actionEnregistrer, 
#                             self.actionValiderTout, 
#                             self.actionAnnulerTout,
                           ]
    def createMenus(self):
        self.listemenus = []
        '''menu base de Cloisons'''
        menubase = QtGui.QMenu("Base de cloisons", self)
        for action in self.actionsfichier:
            menubase.addAction(action)
        u'''menu insérer'''   
        menuinserer = QtGui.QMenu(u'Insérer forme')
        for action in self.actionsinserer :
            menuinserer.addAction(action)
        u'''menu Assigner'''   
        self.listemenus.append(menubase)
        self.listemenus.append(menuinserer)
        
    def createToolBar(self):
        self.toolbars = []
        toolbarfichier = QtGui.QToolBar('Base', self)
        toolbarfichier.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        for action in self.actionsfichier:
            toolbarfichier.addAction(action)
        
        toolbarinserer = QtGui.QToolBar(u'Insérer', self)
        toolbarinserer.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        for action in self.actionsinserer: 
            toolbarinserer.addAction(action)
        
        self.toolbars.append(toolbarfichier)
        self.toolbars.append(toolbarinserer)
    
    def rotation(self, value):
        '''
        Attention : La rotation n'est pas faite en dur (ie dans le modele), comme les homothéties, mais seulement en visualisation.
        TODO: homogénéiser les actions 'rotation' et 'homothétie'
        '''
        for item in self.scene.selectedItems() :
            item.angle = value
#             item.updateTransform()
            item.rotate()
#             item.setRotation(value)
    
    def transformRAZ(self):
        trace(self)
#         for item in self.scene.selectedItems() : 
#             item.angle = 0.0
#             item.homx = item.homy = 1.0
#             item.shearx = item.sheary = 0.0
#             item.updateTransform()
        self.sb_rotation.setValue(0)
#         self.dsb_homx.setValue(1.0)
#         self.dsb_homy.setValue(1.0)
#         self.dsb_shearx.setValue(0.0)
#         self.dsb_sheary.setValue(0.0)
    
    def homothetieX(self, value):
#         trace(self, value)
        for item in self.scene.selectedItems() :
            item.homx = value
            if value == 1.0 : return
#             item.scaleNew()
            item.hardScale()
            self.dsb_homx.setValue(1.0)
#             item.updateTransform()
#             item.setScale(value)
#             item.scale((value, 1.0))
        
    def homothetieY(self, value):
        for item in self.scene.selectedItems() :
            item.homy = value
            if value == 1.0 : return
#             item.updateTransform()
            item.hardScale()
            self.dsb_homy.setValue(1.0)
#             item.scale((1.0, value))
        
    def createConnections(self):
        '''La liste des items selectionnés a changé'''
        self.connect(self.scene, SIGNAL("selectionChanged()"), self.updateUi)
        
        '''Transformations géometriques'''
        self.connect(self.sb_rotation, SIGNAL("valueChanged(int)"), self.rotation)
        self.connect(self.dsb_homx, SIGNAL("valueChanged(double)"), self.homothetieX)
        self.connect(self.dsb_homy, SIGNAL("valueChanged(double)"), self.homothetieY)
#         self.connect(self.dsb_shearx, SIGNAL("valueChanged(double)"), self.cisaillementX)
#         self.connect(self.dsb_sheary, SIGNAL("valueChanged(double)"), self.cisaillementY)
        self.connect(self.tb_aligner, SIGNAL("clicked()"), self.alignerEnZero)
        self.connect(self.tb_pointBase, SIGNAL("clicked()"), self.definirPointDeBase)
        self.connect(self.tb_raz, SIGNAL("clicked()"), self.transformRAZ)
        self.connect(self.tb_symetrieH, SIGNAL("clicked()"), self.symetrieH)
        self.connect(self.tb_symetrieV, SIGNAL("clicked()"), self.symetrieV)
        for action in self.actionsinserer :
            self.connect(action, SIGNAL("triggered(bool)"), self.insert)
#         for action in self.actionsassigner : 
#             self.connect(action, SIGNAL("triggered(bool)"), self.setRole)
        ''' Afficher/cacher '''
#         self.connect(self.actionSuperposer, SIGNAL("triggered()"), self.superposer)
#         self.connect(self.actionChoisirSuperposition, SIGNAL("triggered()"), self.choisirCloisonFantome)
#         for cb in (
#                     self.cb_showgrid, 
#                     self.cb_showpoints,
#                    self.cb_ancrages, 
#                     self.cb_joncs,
#                     self.cb_reperes,
#                     self.cb_renforts,
#                     self.cb_trous,
#                     self.cb_raccords,
#                     self.cb_tout
#                     ) :
#
        ''' Ouvrir, sauvegarder LA BASE, annuler tout, valider tout'''
#         self.connect(self.actionOuvrirBase, SIGNAL("triggered()"), self.openBase)
#         self.connect(self.actionEnregistrerBase, SIGNAL("triggered()"), self.saveBase)
#         self.connect(self.actionEnregistrerBaseSous, SIGNAL("triggered()"), self.saveBaseAs)
#         self.connect(self.actionValiderTout, SIGNAL("triggered()"), self.validateAll)
#         self.connect(self.actionAnnulerTout, SIGNAL("triggered()"), self.undoAll)
        
#        ''' Renommer '''
#         self.connect(self.actionRenommer, SIGNAL("triggered()"), self.rename)
        '''Validation, annulation'''
#         self.connect(self.actionValider, SIGNAL("triggered()"), self.validate)
#         self.connect(self.actionAnnuler, SIGNAL("triggered()"), self.undo)
        ''' Vue, Mise à l'échelle dessin '''
        self.connect(self.cb_showgrid, SIGNAL("toggled(bool)"), self.showGrid)
        self.connect(self.cb_showpoints, SIGNAL("toggled(bool)"), self.showPoints)
        self.connect(self.cb_numerotation, SIGNAL("toggled(bool)"), self.showNumbers)
        self.connect(self.pb_presize,SIGNAL("clicked()"),self.recadre)
#         self.connect(self.actionAfficherGrille,SIGNAL("clicked()"),self.afficherGrille)
#         self.connect(self.actionAfficherPoints,SIGNAL("clicked()"),self.afficherPoints)
# 
        '''Raccord cloisons diagonales'''
#         self.actionRaccorder = QtGui.QAction(u"Définir raccord", self.scene())
#         self.connect(self.actionRaccorder, SIGNAL("triggered()"), self.raccorder)
        
#     def openCloison(self, filename=None):
#         '''Ouvrir une seule cloison, afficher ses shapes sur la cloison courante'''
#         alert(self, 'TODO:')
    def selectedBigItems(self):
        bigitems = []
        for item in self.scene.selectedItems() : 
            if isinstance(item, (EGraphicsProfilItem, EGraphicsGabaritItem)) : 
                bigitems.append(item)
        return bigitems
    
    def selectedItems(self):
        return self.scene.selectedItems()
            
    def definirPointDeBase(self):
        '''Un noeud unique doit être sélectionné'''
        selection = self.selectedItems()
        if len(selection) != 1 : 
            alert(self, u"Sélectionnez un seul point de base.")
            return
        elif not isinstance(selection[0], Noeud):
            alert(self, u"Sélectionnez d'abord le point de base.")
            return
        parentitem = selection[0].parentItem()#On s'adresse au parent du noeud
        parentitem.setBaseNode(selection[0])
    
    def alignerEnZero(self):
        trace(self, 'TODO:')
        for item in self.selectedBigItems() : 
            item.translate((0,0))
                
    def symetrieV(self):
        trace(self)    
        for item in self.selectedBigItems() : 
            item.symetrie(1)
    
    def symetrieH(self):
        trace(self)    
        for item in self.selectedBigItems() : 
            item.symetrie(0)
            
    def validate(self):#inutile
        '''
        Validation des éléments.
        Les shapes graphiques actuelles sont passées au modele (et transformées par le modele).
        '''
        for item in self.scene.items():
            item.validate()
        return None
                  
        
#     def _resizeView(self) :
    
    def recadre(self):
        self.scene.recadre()
        self.wgraphicsview.fitInView(self.scene.sceneRect(), mode=Qt.KeepAspectRatio)
#         self._resizeView()
    
    def _getScene(self):
        return self.wgraphicsview.scene
    def _setScene(self, scene):
        self.wgraphicsview.scene = scene
    scene = property(fget=_getScene, fset=_setScene, fdel=None, doc='la scene')
    
    def _getView(self):
        return self.wgraphicsview
    view = property(fget=_getView, doc='la vue')
    
    def insert(self):
        '''Switch pour insertion de formes.'''
        toinsert = unicode(self.sender().objectName()).replace('actionInserer','').lower()
        self.scene.insertmode = toinsert
    

#########POUR test (pas de mainwindow =>  j'ai pas les toolbar) ###########
    
UiguiMainClass, UiguiMainClassType = loadUiType(Path(SOURCES_DIR,"graphics","main.ui"))
class GuiMain(UiguiMainClassType, UiguiMainClass):
    def __init__(self):
        UiguiMainClassType.__init__(self)
        self.setupUi(self)
        self.editor = GuiProfilEditor()
        self.setCentralWidget(self.editor)
        self.createToolBarsAndMenus()
        self.createConnexions()
        
    def createConnexions(self):
        ''' Menu Fichier '''
        self.connect(self.actionQuitter,SIGNAL("triggered()"),self,SLOT("close()"))
        self.actionQuitter.setShortcut(self.tr("Ctrl+Q"))
    
    def createToolBarsAndMenus(self) :
        ''' 
        - Ajout de la barre d'outils
        '''
        for menu in self.editor.listemenus :
            self.menuBar().addMenu(menu)
        for toolbar in self.editor.toolbars : 
            self.addToolBar(Qt.LeftToolBarArea, toolbar)
            #toolbar.setOrientation(Qt.Vertical)
            toolbar.show()
        self.toolBar.hide()
            
if __name__ == "__main__":
    a = QtGui.QApplication(sys.argv)
#     QtGui.qApp.installEventFilter(a)
    mw = GuiMain()
    mw.show() 
    sys.exit(a.exec_())
    
